package com.test.consumer.listener;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.test.consumer.config.RabbitConfig;
import com.test.consumer.config.RabbitMQConfig;
import com.test.consumer.model.User;
import com.test.consumer.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Slf4j
@Component
public class ConsumerListener {

    @Autowired
    UserService userService;
    @Value("${qos:5}")
    private Integer basicQos;

    @RabbitListener(queues = RabbitConfig.USER_QUEUE, containerFactory = RabbitMQConfig.CUSTOM_CONTAINER_FACTORY)
    public void receiveSecKillOrderMessage(Message message, Channel channel) {
        //设置预抓取总数
        //https://my.oschina.net/hncscwc/blog/195560
        //然而在实际使用过程中，由于消费者自身处理能力有限，
        // 从rabbitmq获取一定数量的消息后，希望rabbitmq不再将队列中的消息推送过来，
        // 当对消息处理完后（即对消息进行了ack，并且有能力处理更多的消息）再接收来自队列的消息。
        // 在这种场景下，我们可以通过设置basic.qos信令中的prefetch_count来达到这种效果
        try {
            channel.basicQos(basicQos);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //1.转换消息格式
        User user = JSON.parseObject(message.getBody(), User.class);

        //2.基于业务层完成同步mysql的操作
        int result = userService.createUser(user);
        if (result > 0) {
            //同步mysql成功
            //向消息服务器返回成功通知
            try {
                /**
                 * 第一个参数:消息的唯一标识
                 * 第二个参数:是否开启批处理
                 */
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            //同步mysql失败
            //向消息服务器返回失败通知
            try {
                /**
                 * 第一个参数:消息的唯一标识
                 * 第二个参数: true所有消费者都会拒绝这个消息,false只有当前消费者拒绝
                 * 第三个参数: false当前消息会进入到死信队列(延迟消息队列),true 当前的消息会重新进入到原有队列中,默认回到头部
                 */
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
